//===============================================================================
// Microsoft patterns & practices
// Smart Client Software Factory
//===============================================================================
// Copyright (C) Microsoft Corporation.  All rights reserved.
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE.
//===============================================================================
// The example companies, organizations, products, domain names,
// e-mail addresses, logos, people, places, and events depicted
// herein are fictitious.  No association with any real company,
// organization, product, domain name, email address, logo, person,
// places, or events is intended or should be inferred.
//===============================================================================

//----------------------------------------------------------------------------------------
// patterns & practices - Smart Client Software Factory - Guidance Package
//
// This file was generated by the "Add View" recipe.
//
// A presenter calls methods of a view to update the information that the view displays. 
// The view exposes its methods through an interface definition, and the presenter contains
// a reference to the view interface. This allows you to test the presenter with different 
// implementations of a view (for example, a mock view).
//
// For more information see:
// ms-help://MS.VSCC.v80/MS.VSIPCC.v80/ms.scsf.2006jun/SCSF/html/03-030-Model%20View%20Presenter%20%20MVP%20.htm
//
// Latest version of this Guidance Package: http://go.microsoft.com/fwlink/?LinkId=62182
//----------------------------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Security.Authentication;
using System.Threading;
using GlobalBank.BasicAccounts.Interface.Constants;
using GlobalBank.BasicAccounts.Interface.Services;
using GlobalBank.BasicAccounts.Properties;
using GlobalBank.BranchSystems.Interface.Services;
using GlobalBank.Infrastructure.Interface;
using GlobalBank.Infrastructure.Interface.BusinessEntities;
using GlobalBank.Infrastructure.Interface.Services;
using Microsoft.Practices.CompositeUI;
using Microsoft.Practices.CompositeUI.EventBroker;
using Microsoft.Practices.CompositeUI.Utility;
using Microsoft.Practices.ObjectBuilder;

namespace GlobalBank.BasicAccounts.Module
{
	public class PurchaseCDViewPresenter : Presenter<IPurchaseCDView>
	{
		[EventPublication(EventTopicNames.CustomerProductsUpdated, PublicationScope.Global)]
		public event EventHandler<EventArgs<Customer>> CustomerProductsUpdated;

		private IQuoteService _quoteService = null;
		private ICustomerAccountService _customerAccountsService = null;
		private IAccountService _accountService = null;
		private QueueEntry _queueEntry = null;
		private Rate[] _rates;


		[InjectionConstructor]
		public PurchaseCDViewPresenter
			(
			[ComponentDependency("QueueEntry")] QueueEntry queueEntry,
			[ServiceDependency] IQuoteService quoteService,
			[ServiceDependency] ICustomerAccountService customerAccountsService,
			[ServiceDependency] IAccountService accountService
			)
		{
			_queueEntry = queueEntry;
			_quoteService = quoteService;
			_customerAccountsService = customerAccountsService;
			_accountService = accountService;
		}

		public override void OnViewReady()
		{
			View.ShowRatesTable(GetRatesTable());
			View.ShowCustomerAccounts(GetCustomerAccounts());
			View.Clear();
		}

		public virtual Rate[] GetRatesTable()
		{
			if (_rates == null)
				_rates = _quoteService.GetRates();
			return _rates;
		}

		public virtual Account[] GetCustomerAccounts()
		{
			Guard.ArgumentNotNull(_queueEntry.Person, "Person");
			Customer customer = _queueEntry.Person as Customer;
			Guard.ArgumentNotNull(customer, "Person");


			Account[] accounts = _customerAccountsService.GetCustomerAccounts(customer);

			List<Account> result = new List<Account>();
			foreach (Account account in accounts)
			{
				if (account.AccountType != AccountType.CD) result.Add(account);
			}

			return result.ToArray();
		}

		public virtual decimal GetInterestRate(decimal amount, int duration)
		{
			Rate[] rates = GetRatesTable();

			Rate rate = Array.Find<Rate>(rates, delegate(Rate match)
			                                    	{
			                                    		return amount >= match.MinimumAmount && amount <= match.MaximumAmount &&
			                                    		       duration >= match.Start && duration <= match.End;
			                                    	});

			if (rate == null)
			{
				return 0M;
			}

			return rate.InterestRate;
		}

		public void CalculateInterestRate(decimal amount, int duration)
		{
			decimal rate = GetInterestRate(amount, duration);
			if (rate == 0)
			{
				View.ShowMessage(Properties.Resources.RateNotFound);
			}
			View.ShowInterestRate(rate);
		}

		public void PurchaseCD(Account source, decimal amount, int duration)
		{
			// TODO: workflow. parameters should go on config
			if (amount >= 10000 && !Thread.CurrentPrincipal.IsInRole("BranchManager"))
			{
				View.ShowMessage(Resources.UserNotAuthorizedMessage);
				View.ShowApproval(true);
			}
			else
			{
				InnerPurchaseCD(source, amount, duration);
			}
		}

		public void ApproveAndPurchaseCD(Account source, decimal amount, int duration)
		{
			try
			{
				IImpersonationService impersonator = WorkItem.Services.Get<IImpersonationService>();
				using (IImpersonationContext context = impersonator.Impersonate())
				{
					PurchaseCD(source, amount, duration);
				}
			}
			catch (AuthenticationException)
			{
				View.ShowMessage(Resources.UserNotAuthorizedMessage);
			}
		}

		public void OnCloseView()
		{
			View.Clear();
			CloseView();
		}

		private void InnerPurchaseCD(Account source, decimal amount, int duration)
		{
			try
			{
				decimal rate = GetInterestRate(amount, duration);
				if (rate == 0)
				{
					View.ShowMessage(Properties.Resources.RateNotFound);
					return;
				}
				_accountService.PurchaseCertificateOfDeposit(Customer, source, amount, duration, rate);
				View.ShowMessage(String.Empty);
				View.ShowCustomerAccounts(GetCustomerAccounts());
				OnCustomerProductsUpdated();
				OnCloseView();
			}
			catch (InsufficientFundsException)
			{
				View.ShowMessage(Resources.IsufficientFundsMessage);
			}
		}

		public virtual void OnCustomerProductsUpdated()
		{
			if (CustomerProductsUpdated != null)
			{
				CustomerProductsUpdated(this, new EventArgs<Customer>(Customer));
			}
		}

		protected Customer Customer
		{
			get { return _queueEntry.Person as Customer; }
		}
	}
}
